package no.nordicsemi.android.nrfmesh.auth.data;

import android.os.Handler;
import android.os.Looper;

import androidx.annotation.Nullable;

import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;

import no.nordicsemi.android.nrfmesh.auth.util.CredentialStore;
import no.nordicsemi.android.nrfmesh.database.dao.LocalAccountDao;
import no.nordicsemi.android.nrfmesh.database.entity.LocalAccount;

/**
 * AccountRepository
 *
 * 要点：
 * - 所有 Room DAO 写操作放 I/O 线程；
 * - 提供 listAsync 主线程回调；
 * - 同时提供“仅限后台线程调用”的 list()，避免 AuthViewModel 回退路径失效。
 */
public class AccountRepository {

    private final LocalAccountDao dao;
    private final CredentialStore cred;

    private final ExecutorService io = Executors.newSingleThreadExecutor();
    private final Handler main = new Handler(Looper.getMainLooper());

    public AccountRepository(LocalAccountDao dao, CredentialStore cred){
        this.dao = dao;
        this.cred = cred;
    }

    /* ========== 列表 / 最近 ========== */

    /** 异步获取本地账号列表（UI 线程安全，回调切回主线程） */
    public void listAsync(Consumer<List<LocalAccount>> callback){
        io.execute(() -> {
            List<LocalAccount> data = dao.list();
            main.post(() -> callback.accept(data));
        });
    }

    /**
     * 同步列表方法（仅供“后台线程”调用）。
     * 说明：AuthViewModel.loadAccounts() 在反射不到 listAsync 时会回退调用 list()。
     * 之前这里直接 throw 导致“切换账户列表一直为空”。现在允许在后台线程读取。
     */
    public List<LocalAccount> list(){
        if (Looper.myLooper() == Looper.getMainLooper()) {
            throw new IllegalStateException("AccountRepository.list() must NOT be called on main thread");
        }
        return dao.list();
    }

    /** 轻量首选项读写 */
    public @Nullable String getLastUser(){ return cred.getLastUser(); }
    public void setLastUser(String userId){ cred.setLastUser(userId); }

    /* ========== 记住账号 ========== */

    public void remember(String userId, String displayName, String pwdPlain, boolean autoLogin){
        io.execute(() -> {
            long now = System.currentTimeMillis();
            LocalAccount a = new LocalAccount();
            a.userId = userId;
            a.displayName = displayName;
            a.rememberOnDevice = true;
            a.autoLogin = autoLogin;
            a.lastLoginAt = now;

            dao.upsert(a);
            cred.savePassword(userId, pwdPlain);
            cred.setAutoLogin(userId, autoLogin);
            cred.setLastUser(userId);
        });
    }

    /* ========== 忘记账号 ========== */

    public void forget(String userId){
        io.execute(() -> {
            dao.delete(userId);
            cred.removePassword(userId);

            String last = cred.getLastUser();
            if (last != null && last.equals(userId)) {
                List<LocalAccount> rest = dao.list();
                if (rest == null || rest.isEmpty()) {
                    cred.clearLastUser();
                } else {
                    cred.setLastUser(rest.get(0).userId);
                }
            }
        });
    }

    /* ========== 密码 / 自动登录（读取为轻量操作） ========== */

    public String getSavedPassword(String userId){ return cred.getPassword(userId); }
    public boolean isAutoLogin(String userId){ return cred.isAutoLogin(userId); }

    /* ========== 最近使用时间 ========== */

    public void touch(String userId){
        io.execute(() -> {
            dao.touch(userId, System.currentTimeMillis());
            cred.setLastUser(userId);
        });
    }

    /* ========== 删除本地账号（带 last_user 修正） ========== */

    public void deleteLocalAccount(String userId){
        io.execute(() -> {
            dao.delete(userId);
            cred.removePassword(userId);

            String last = cred.getLastUser();
            if (last != null && last.equals(userId)) {
                List<LocalAccount> rest = dao.list();
                if (rest == null || rest.isEmpty()) {
                    cred.clearLastUser();
                } else {
                    cred.setLastUser(rest.get(0).userId);
                }
            }
        });
    }

    /* ========== 设置自动登录 ========== */

    public void setAutoLogin(String userId, boolean enabled){
        io.execute(() -> {
            cred.setAutoLogin(userId, enabled);
            LocalAccount a = dao.get(userId);
            if (a != null) {
                a.autoLogin = enabled;
                dao.upsert(a);
            }
        });
    }

    /** 仅清空“最近账号”（用于【切换账户】），不动 autoLogin 和密码 */
    public void clearLastUser() {
        io.execute(cred::clearLastUser);
    }

    /** 退出登录统一逻辑（保留你现有用法） */
    public void logout(@Nullable String currentUserId,
                       boolean disableAutoLoginForCurrent,
                       boolean removeLocalPassword) {
        io.execute(() -> {
            if (currentUserId != null) {
                if (disableAutoLoginForCurrent) {
                    cred.setAutoLogin(currentUserId, false);
                    LocalAccount a = dao.get(currentUserId);
                    if (a != null) { a.autoLogin = false; dao.upsert(a); }
                }
                if (removeLocalPassword) {
                    cred.removePassword(currentUserId);
                }
            }
            cred.clearLastUser();
        });
    }
}
